package com.qinglei.recoup.hmp.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qinglei.recoup.common.domain.CommonConstant;
import com.qinglei.recoup.common.domain.CommonRes;
import com.qinglei.recoup.common.domain.RadarVersionEnum;
import com.qinglei.recoup.common.exception.RedisConnectException;
import com.qinglei.recoup.common.service.RedisService;
import com.qinglei.recoup.common.service.impl.ProductCache;
import com.qinglei.recoup.common.utils.JsonUtils;
import com.qinglei.recoup.hmp.domain.HmpUserBindDevice;
import com.qinglei.recoup.hmp.domain.HmpUserTag;
import com.qinglei.recoup.hmp.pojo.dto.AddUserBindDeviceDTO;
import com.qinglei.recoup.hmp.pojo.parm.DeviceVersionParam;
import com.qinglei.recoup.hmp.pojo.vo.*;
import com.qinglei.recoup.hmp.service.HmpDeviceService;
import com.qinglei.recoup.hmp.service.HmpUserBindDeviceService;
import com.qinglei.recoup.hmp.service.HmpUserTagService;
import com.qinglei.recoup.system.domain.Bed;
import com.qinglei.recoup.system.domain.BedHealthDailyStatistics;
import com.qinglei.recoup.system.enums.IocUpdateEnum;
import com.qinglei.recoup.system.pojo.AlarmEventItemVO;
import com.qinglei.recoup.system.pojo.PageParam;
import com.qinglei.recoup.system.pojo.RealTimeDataVOV4;
import com.qinglei.recoup.system.pojo.RealTimeDataVOV7;
import com.qinglei.recoup.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>小程序设备相关服务</p>
 *
 * @author shiyupeng
 * @date 2022/1/11
 */
@Service
@Slf4j
public class HmpDeviceServiceImpl implements HmpDeviceService {

    @Autowired
    private HmpUserBindDeviceService hmpUserBindDeviceService;

    @Autowired
    private ProductCache productCache;

    @Autowired
    private HmpUserTagService hmpUserTagService;

    @Autowired
    private BedService bedService;

    @Autowired
    private EventProcService eventProcService;

    @Autowired
    private BedHealthDailyStatisticsService bedHealthDailyStatisticsService;

    @Autowired
    private RadarUserDataFourService radarUserDataFourService;
    @Autowired
    private RedisService redisService;
    @Resource
    private RadarDataService radarDataService;

    /**
     * 实时数据模式设置开关
     */
    @Value("${hmp.device.realtime-mode.enable:false}")
    private Boolean realtimeModeEnable;
    /**
     * 实时数据模式设置时长 分钟
     */
    @Value("${hmp.device.realtime-mode.time:10}")
    private Integer realtimeModeTime;
    /**
     * 实时数据模式检查设置是否成功，重试次数
     */
    @Value("${hmp.device.realtime-mode.retry-count:200}")
    private Integer realtimeModeRetryCount;
    /**
     * 实时数据模式检查设置是否成功接口，每次重试间隔时长 毫秒
     */
    @Value("${hmp.device.realtime-mode.retry-wait:300}")
    private Integer realtimeModeRetryWait;


    /**
     * 检查当前用户是否已绑定设备
     *
     * @param userId
     * @return
     */
    @Override
    public CommonRes<DeviceCheckBindVO> checkBind(Long userId) {
        DeviceCheckBindVO deviceCheckBindVO = new DeviceCheckBindVO();
        deviceCheckBindVO.setIsBind(0);
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).last("order by is_default desc, create_time desc limit 1"));
        if (hmpUserBindDevice != null) {
            deviceCheckBindVO.setIsBind(1);
            deviceCheckBindVO.setDefaultSn(hmpUserBindDevice.getDeviceSn());
        }
        return CommonRes.ok(deviceCheckBindVO);
    }

    /**
     * 设置设备使用者标签接口
     *
     * @param userId
     * @param param
     * @return
     */
    @Override
    public CommonRes<Object> bindUserTag(Long userId, BindUserTagParam param) {
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getDeviceSn, param.getSn()));
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        hmpUserBindDevice.setUserTagId(param.getUserTagId());
        hmpUserBindDeviceService.updateById(hmpUserBindDevice);
        return CommonRes.ok();
    }

    /**
     * 设置默认设备接口
     *
     * @param userId
     * @param param
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonRes<Object> setDefaultDevice(Long userId, DeviceSnParam param) {
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getDeviceSn, param.getSn()));
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        if (hmpUserBindDevice.getIsDefault() == 1) {
            return CommonRes.ok();
        }
        HmpUserBindDevice cancelDefault = new HmpUserBindDevice();
        cancelDefault.setIsDefault(0);
        hmpUserBindDeviceService.update(cancelDefault, Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getIsDefault, 1));

        hmpUserBindDevice.setIsDefault(1);
        hmpUserBindDeviceService.updateById(hmpUserBindDevice);

        return CommonRes.ok();
    }

    /**
     * 取消绑定设备接口
     *
     * @param param
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonRes<Object> cancelBindDevice(Long userId, DeviceSnParam param) {
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getDeviceSn, param.getSn()));
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        // 删除当前设备绑定关系
        hmpUserBindDeviceService.removeById(hmpUserBindDevice.getId());

        if (hmpUserBindDevice.getIsDefault() == 1) {
            // 设置一个新的默认设备
            this.selectNewDefaultDevice(userId);
        }
        return CommonRes.ok();
    }

    /**
     * 进入实时数据模式接口
     *
     * @param userId
     * @param param
     */
    @Override
    public CommonRes<Object> enterRealtime(Long userId, DeviceSnParam param) {
        if (!this.realtimeModeEnable) {
            return CommonRes.ok("实时模式设置未开启");
        }
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getDeviceSn, param.getSn()));
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        Map<String, Object> items = new HashMap<>();
        Random random = new Random();
        int modeCheckSet = random.nextInt();
        int modeTime = this.realtimeModeTime;
        items.put("V4:MODE_CHECK", modeCheckSet);
        items.put("V4:MODE_TIME", modeTime);
        log.info("enterRealtime set MODE_CHECK:{},MODE_TIME:{}", modeCheckSet, modeTime);
        boolean res = productCache.setDevicePropertyStatus(hmpUserBindDevice.getDeviceSn(), hmpUserBindDevice.getIotProductKey(), items);
        if (!res) {
            return CommonRes.failed("设置设备物联网属性失败");
        }
        int retryTimes = 0;
        while (retryTimes < this.realtimeModeRetryCount) {
            Map<String, String> propertyStatus = productCache.getDevicePropertyStatus(hmpUserBindDevice.getDeviceSn(), hmpUserBindDevice.getIotProductKey(),"V4");
            if (propertyStatus == null) {
                return CommonRes.failed("获取设备物联网属性失败");
            }
            String modeCheck = propertyStatus.get("V4:MODE_CHECK");
            if (modeCheck != null) {
                log.info("enterRealtime get MODE_CHECK:{}, times:{}", modeCheck, retryTimes);
                int modeCheckGet = Integer.parseInt(modeCheck);
                if (modeCheckGet == modeCheckSet) {
                    log.info("enterRealtime success times:{}", retryTimes);
                    return CommonRes.ok("设置实时模式成功");
                }
            }
            retryTimes++;
            try {
                Thread.sleep(this.realtimeModeRetryWait);
            } catch (InterruptedException e) {
                log.error("enterRealtime sleep error", e);
                break;
            }
        }

        return CommonRes.failed("设置设备实时模式失败");
    }

    /**
     * 查询更多设备接口
     *
     * @param userId
     * @param param
     * @return
     */
    @Override
    public CommonRes<IPage<DeviceVO>> getDevicePage(Long userId, PageParam param) {
        IPage<DeviceVO> res = hmpUserBindDeviceService.selectDevicePage(param, userId);
        return CommonRes.ok(res);
    }

    /**
     * 设置设备属性接口
     *
     * @param userId
     * @param param
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonRes<Object> setDeviceAttr(Long userId, DeviceAttrParam param) {
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getDeviceSn, param.getSn()));
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        // 更新本地数据库保存的属性值
        if (param.getPoliceStatus() != null || param.getReportStatus() != null) {
            if (param.getReportStatus() != null) {
                hmpUserBindDevice.setReportStatus(param.getReportStatus());
            }
            if (param.getPoliceStatus() != null) {
                hmpUserBindDevice.setPoliceStatus(param.getPoliceStatus());
            }
            hmpUserBindDeviceService.updateById(hmpUserBindDevice);
        }
        // 更新物联网平台属性
        if (param.getBedLamp() != null || param.getNetworkLamp() != null) {
            Map<String, Object> items = new HashMap<>();
            if (param.getBedLamp() != null) {
                items.put("V4:LIGHT_L_1", param.getBedLamp());
            }
            if (param.getNetworkLamp() != null) {
                items.put("V4:LIGHT_L_2", param.getNetworkLamp());
            }
            boolean res = productCache.setDevicePropertyStatus(hmpUserBindDevice.getDeviceSn(), hmpUserBindDevice.getIotProductKey(), items);
            if (!res) {
                return CommonRes.failed("设置设备物联网属性失败");
            }
        }

        return CommonRes.ok();
    }

    /**
     * 获取睡眠日历接口
     *
     * @param userId
     * @param param
     * @return
     */
    @Override
    public CommonRes<DeviceDetailVO> getDeviceDetail(Long userId, DeviceDetailParam param) {
        HmpUserBindDevice hmpUserBindDevice = null;
        if (StringUtils.isEmpty(param.getSn())) {
            // 如果没传sn码，获取默认设备
            hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                    .eq(HmpUserBindDevice::getUserId, userId).last("order by is_default desc, create_time desc limit 1"));
        } else {
            // 如果传了sn码，使用参数的sn码查询设备
            hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                    .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getDeviceSn, param.getSn()));
        }
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        DeviceDetailVO deviceDetailVO = new DeviceDetailVO();
        deviceDetailVO.setSn(hmpUserBindDevice.getDeviceSn());
        deviceDetailVO.setIsDefault(hmpUserBindDevice.getIsDefault());

        // 是否存在更多设备
        deviceDetailVO.setHasMoreDevice(0);
        int deviceCount = hmpUserBindDeviceService.count(Wrappers.<HmpUserBindDevice>lambdaQuery().eq(HmpUserBindDevice::getUserId, userId));
        if (deviceCount > 1) {
            deviceDetailVO.setHasMoreDevice(1);
        }

        // 查询使用者标签名称
        if (hmpUserBindDevice.getUserTagId() != null) {
            HmpUserTag hmpUserTag = hmpUserTagService.getById(hmpUserBindDevice.getUserTagId());
            if (hmpUserTag != null) {
                deviceDetailVO.setUserTagName(hmpUserTag.getName());
            }
        }

        // 查询监测状态
        Bed bed = bedService.getById(hmpUserBindDevice.getBedId());
        if (bed == null) {
            return CommonRes.failed("设备数据不全");
        }
        if (bed.getIsRadarOnline() == Bed.RADAR_ONLINE) {
            deviceDetailVO.setStatus(DeviceDetailVO.NORMAL);
            deviceDetailVO.setStatusText("实时监测中");
        } else {
            deviceDetailVO.setStatus(DeviceDetailVO.STOP);
            deviceDetailVO.setStatusText("您的设备已停止监测");
        }

        // 查询未读报警数
        Integer missedEventNum = eventProcService.getAlarmEventCount(hmpUserBindDevice.getBedId());
        deviceDetailVO.setAlarmCount(missedEventNum);

        // 查询设备属性数据
        if (param.getNeedDeviceAttr() == 1) {
            DeviceAttrVO deviceAttribute = this.getDeviceAttribute(hmpUserBindDevice);
            deviceDetailVO.setDeviceAttr(deviceAttribute);
        }

        // 查询日历数据
        if (param.getNeedCalendarData() == 1) {
            if (StringUtils.isEmpty(param.getEndDate())) {
                return CommonRes.failed("参数缺少日历截止日期");
            }
            LocalDate endDate;
            LocalDate startDate;
            if (param.getIsBefore() != null && param.getIsBefore() == 1) {
                startDate = LocalDate.parse(param.getEndDate()).plusDays(1);
                endDate = startDate.plusDays(param.getDays() - 1);
            } else {
                endDate = LocalDate.parse(param.getEndDate()).minusDays(1);
                startDate = endDate.minusDays(param.getDays() - 1);
            }

            List<CalendarDayItemVO> calendarData = this.getCalendarData(hmpUserBindDevice.getBedId(), startDate, endDate);
            deviceDetailVO.setCalendarData(calendarData);
        }

        return CommonRes.ok(deviceDetailVO);
    }

    /**
     * 获取设备实时数据接口
     *
     * @param userId
     * @param sn
     * @param second
     * @return
     */
    @Override
    public CommonRes<DeviceRealTimeVO> getRealTimeData(Long userId, String sn, Integer second, Integer tenantId) {
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getDeviceSn, sn));
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        RealTimeDataVOV4 realTimeData = null;
        try {
            realTimeData = radarUserDataFourService.getRealTimeData(hmpUserBindDevice.getBedId(), second, tenantId);
        } catch (RedisConnectException e) {
            log.error("getRealTimeData error userId:{},sn:{},second:{},bedId,{}", userId, sn, second, hmpUserBindDevice.getBedId(), e);
        }
        if (realTimeData == null) {
            return CommonRes.failed("无法获取实时数据");
        }
        DeviceRealTimeVO deviceRealTimeVO = new DeviceRealTimeVO();
        BeanUtils.copyProperties(realTimeData, deviceRealTimeVO);

        // 查询未读报警数
        Integer missedEventNum = eventProcService.getAlarmEventCount(hmpUserBindDevice.getBedId());
        deviceRealTimeVO.setAlarmCount(missedEventNum);

        return CommonRes.ok(deviceRealTimeVO);
    }

    /**
     * 查询设备报警信息列表接口
     *
     * @param userId
     * @param param
     * @return
     */
    @Override
    public CommonRes<IPage<AlarmEventItemVO>> getAlarmEventList(Long userId, AlarmEventPageParam param) {
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getDeviceSn, param.getSn()));
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        LocalDate startDate;
        if (StringUtils.isEmpty(param.getMonth())) {
            LocalDate now = LocalDate.now();
            startDate = LocalDate.of(now.getYear(), now.getMonthValue(), 1);
        } else {
            startDate = LocalDate.parse(param.getMonth() + "-01");
        }
        LocalTime time = LocalTime.parse("00:00:00");
        LocalDateTime startTime = LocalDateTime.of(startDate, time);
        LocalDateTime endTime = startTime.plusMonths(1);
        IPage pageParam = new Page();
        pageParam.setSize(param.getPageSize());
        pageParam.setCurrent(param.getPageNum());
        IPage<AlarmEventItemVO> alarmEventPage = eventProcService.pageAlarmEventList(hmpUserBindDevice.getBedId(), startTime, endTime, pageParam);
        return CommonRes.ok(alarmEventPage);
    }

    /**
     * 将报警信息设置为已读状态接口
     *
     * @return
     */
    @Override
    public CommonRes<Object> setReadAlarmEvent(Long userId, Integer tenantId, AlarmEventFinishParam param) {
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getDeviceSn, param.getSn()));
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        LocalDate startDate;
        if (StringUtils.isEmpty(param.getMonth())) {
            LocalDate now = LocalDate.now();
            startDate = LocalDate.of(now.getYear(), now.getMonthValue(), 1);
        } else {
            startDate = LocalDate.parse(param.getMonth() + "-01");
        }
        LocalTime time = LocalTime.parse("00:00:00");
        LocalDateTime startTime = LocalDateTime.of(startDate, time);
        LocalDateTime endTime = startTime.plusMonths(1);
        Boolean res = eventProcService.finishAlarmEvent(userId, tenantId, hmpUserBindDevice.getBedId(), startTime, endTime);
        return CommonRes.ok(res);
    }

    /**
     * 查询设备属性数据
     *
     * @param hmpUserBindDevice
     * @return
     */
    private DeviceAttrVO getDeviceAttribute(HmpUserBindDevice hmpUserBindDevice) {
        DeviceAttrVO deviceAttrVO = new DeviceAttrVO();
        deviceAttrVO.setPoliceStatus(hmpUserBindDevice.getPoliceStatus());
        deviceAttrVO.setReportStatus(hmpUserBindDevice.getReportStatus());
        Map<String, String> devicePropertyStatus = productCache.getDevicePropertyStatus(hmpUserBindDevice.getDeviceSn(), hmpUserBindDevice.getIotProductKey(),"V4");
        if (devicePropertyStatus != null) {
            if (devicePropertyStatus.get(DEVICE_ATTR_BED_LAMP) != null) {
                deviceAttrVO.setBedLamp(Integer.parseInt(devicePropertyStatus.get(DEVICE_ATTR_BED_LAMP)));
            }
            if (devicePropertyStatus.get(DEVICE_ATTR_NETWORK_LAMP) != null) {
                deviceAttrVO.setNetworkLamp(Integer.parseInt(devicePropertyStatus.get(DEVICE_ATTR_NETWORK_LAMP)));
            }
        }
        return deviceAttrVO;
    }

    /**
     * 获取健康日志数据
     *
     * @param bedId
     * @param startDate
     * @param endDate
     * @return
     */
    private List<CalendarDayItemVO> getCalendarData(Integer bedId, LocalDate startDate, LocalDate endDate) {
        List<BedHealthDailyStatistics> dailyStatistics = bedHealthDailyStatisticsService.list(Wrappers.<BedHealthDailyStatistics>lambdaQuery()
                .eq(BedHealthDailyStatistics::getBedId, bedId).between(BedHealthDailyStatistics::getStatisticsDate, startDate, endDate));
        Map<String, BedHealthDailyStatistics> dataMap = new HashMap<>();
        dailyStatistics.forEach(item -> {
            dataMap.put(item.getStatisticsDate().format(DateTimeFormatter.ISO_LOCAL_DATE), item);
        });
        List<CalendarDayItemVO> calendarData = new ArrayList<>();
        for (LocalDate curDate = startDate; !curDate.isAfter(endDate); curDate = curDate.plusDays(1)) {
            CalendarDayItemVO calendarDayItemVO = new CalendarDayItemVO();
            String date = curDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
            calendarDayItemVO.setDate(date);
            calendarDayItemVO.setScore(0);
            if (dataMap.get(date) != null) {
                calendarDayItemVO.setScore(dataMap.get(date).getScore().intValue());
            }
            calendarData.add(calendarDayItemVO);
        }
        return calendarData;
    }

    /**
     * 选择最新添加的设备设置为默认设备
     *
     * @param userId
     */
    private void selectNewDefaultDevice(Long userId) {
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).last("order by create_time desc limit 1"));
        if (hmpUserBindDevice == null) {
            return;
        }
        hmpUserBindDevice.setIsDefault(1);
        hmpUserBindDeviceService.updateById(hmpUserBindDevice);
    }

    @Override
    public void addHmpDevice(AddUserBindDeviceDTO param) {
        HmpUserBindDevice hmpUserBindDeviceOld = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, param.getUserId()).eq(HmpUserBindDevice::getDeviceSn, param.getSn()));
        if (hmpUserBindDeviceOld != null) {
            throw new RuntimeException("HmpUserBindDevice is Already exists");
        }
        // 查询当前的默认设备
        HmpUserBindDevice defaultDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, param.getUserId())
                .eq(HmpUserBindDevice::getIsDefault, 1)
                .last("limit 1"));

        // 构建新的绑定设备对象
        HmpUserBindDevice hmpUserBindDevice = new HmpUserBindDevice();
        hmpUserBindDevice.setDeviceSn(param.getSn());
        hmpUserBindDevice.setUserId(param.getUserId());
        hmpUserBindDevice.setBedId(param.getBedId());
        hmpUserBindDevice.setIotProductKey(param.getIotProductKey());

        // 如果当前不存在默认设备，则新添加设备设置为默认设备
        if (defaultDevice == null) {
            hmpUserBindDevice.setIsDefault(1);
        }

        hmpUserBindDeviceService.save(hmpUserBindDevice);
    }

    @Override
    public CommonRes<CheckDeviceVersionVo> checkDeviceVersion(DeviceVersionParam param) {
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, param.getUserId()).eq(HmpUserBindDevice::getDeviceSn, param.getSn()));
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        //暂时先去缓存中查看设备的状态信息
        CheckDeviceVersionVo checkDeviceVersionVo = new CheckDeviceVersionVo();
        try {
            String versionStatus = redisService.hget(CommonConstant.JOBIDCACHE_RADAR_STATUS, param.getSn());
            if(StringUtils.isNotEmpty(versionStatus) && IocUpdateEnum.IN_PROGRESS.getCode().equals(versionStatus)){
                checkDeviceVersionVo.setStatus(1);
                checkDeviceVersionVo.setStatusName("正在升级中，请勿断电断网，大约需要2分钟左右，开发小哥哥偶尔会走神儿，最多不会超过10分钟，请耐心等待");
            }
        } catch (RedisConnectException e) {
           log.error("checkDeviceVersion error sn:{} e: {}",param.getSn(),e);
        }
        return CommonRes.ok(checkDeviceVersionVo);
    }


    @Override
    public CommonRes<RealTimeDataVOV7> getMiniRealTimeDataV7(Long userId, String sn, Integer second, Integer tenantId) {
        HmpUserBindDevice hmpUserBindDevice = hmpUserBindDeviceService.getOne(Wrappers.<HmpUserBindDevice>lambdaQuery()
                .eq(HmpUserBindDevice::getUserId, userId).eq(HmpUserBindDevice::getDeviceSn, sn));
        if (hmpUserBindDevice == null) {
            return CommonRes.failed("用户未绑定该设备");
        }
        return this.getRealTimeDataV7(sn,second,tenantId);
    }

    @Override
    public CommonRes<RealTimeDataVOV7> getWebRealTimeDataV7(String sn, Integer second, Integer tenantId) {
        return this.getRealTimeDataV7(sn,second,tenantId);
    }

    private List<Double> setDateee =  new ArrayList();
    public CommonRes<RealTimeDataVOV7> getRealTimeDataV7(String sn, Integer second, Integer tenantId) {
        RealTimeDataVOV7 realTimeDataVOV7 = new RealTimeDataVOV7();
        Bed bedBySn = bedService.getBedBySn(sn);
        if(Objects.isNull(bedBySn)){
            return CommonRes.failed("用户未绑定床位");
        }
        if(RadarVersionEnum.VERSION_V4.getCode().equals(bedBySn.getRadarVersion())){
            RealTimeDataVOV4 realTimeData = null;
            try {
                realTimeData = radarUserDataFourService.getRealTimeData(bedBySn.getId(), second, tenantId);
            } catch (RedisConnectException e) {
                log.error("getRealTimeDataV7 v4 error sn:{},second:{},bedId,{}", sn, second, bedBySn.getId(), e);
            }
            if (realTimeData == null) {
                return CommonRes.failed("无法获取实时数据");
            }
            BeanUtils.copyProperties(realTimeData, realTimeDataVOV7);
            List<Double> breathList = new ArrayList<>();
            if(realTimeData.getBreathPhaseData() != null && realTimeData.getBreathPhaseData().size() == 200){
                breathList = realTimeData.getBreathPhaseData().stream().skip(realTimeData.getBreathPhaseData().size() - 10).collect(Collectors.toList());
            }else {
                for (int i = 0; i < 10; i++) {
                    breathList.add(0.0);
                }
            }
            realTimeDataVOV7.setBreathPhaseData(breathList);
            List<Double> heartList = new ArrayList<>();
            if(realTimeData.getHeartPhaseData()!=null && realTimeData.getHeartPhaseData().size() == 200){
                heartList = realTimeData.getHeartPhaseData().stream().skip(realTimeData.getHeartPhaseData().size() - 100).collect(Collectors.toList());
            }else {
                for (int i = 0; i < 100; i++) {
                    heartList.add(0.0);
                }
            }
            realTimeDataVOV7.setHeartPhaseData(heartList);
            if("1".equals(realTimeDataVOV7.getDeviceType())){
                realTimeDataVOV7.setStatus(5);
            }
            realTimeDataVOV7.setIsOffline(realTimeData.getIsRadarOnline() == 1);
            realTimeDataVOV7.setIsSignal(realTimeData.getIsRadarNetwork() == 0);
            //稳定值
            if(StringUtils.isNotEmpty(realTimeData.getL2R())){

                List<Double> doubleList = JsonUtils.jsonToList(realTimeData.getL2R(), Double.class);
                double abs = Math.abs(doubleList.get(0));
                double stableNum = 0;
                if(abs == 0){
                    stableNum = -1;
                }else {
                    double L2R = abs * 100;
                    if (L2R > 1000) {
                        L2R = 1000;
                    }
                    double numL2r = L2R / 10;
                    stableNum = Math.round(100.0 - numL2r);
                }
                realTimeDataVOV7.setStableNum(stableNum);
            }
        }else if(RadarVersionEnum.VERSION_V7.getCode().equals(bedBySn.getRadarVersion())){
            try {
                RealTimeDataVOV7 realTimeDataV7 = radarDataService.getRealTimeDataV7(sn, second);
                if (Objects.isNull(realTimeDataV7)) {
                    return CommonRes.failed("无法获取实时数据");
                }
                BeanUtils.copyProperties(realTimeDataV7, realTimeDataVOV7);
/*                if(setDateee.size()<6000){
                    setDateee.addAll(realTimeDataVOV7.getHeartPhaseData());
                }
                log.info("getRealTimeDataV7 心跳数据累计数为：{}",setDateee.size());
                if(setDateee.size() == 6000){
                    log.info("getRealTimeDataV7 心跳数据累计6000:{}",setDateee);
                }*/
            } catch (Exception e) {
                log.error("getRealTimeDataV7 v7 error ,sn:{},second:{}", sn, second, e);
            }
        }
        // 查询未读报警数
        Integer missedEventNum = eventProcService.getAlarmEventCount(bedBySn.getId());
        realTimeDataVOV7.setAlarmCount(missedEventNum);
        log.info("getRealTimeDataV7 sn:{} , 返回体为:{}",sn, JsonUtils.objectToJson(realTimeDataVOV7));
        return CommonRes.ok(realTimeDataVOV7);
    }

    @Override
    public void deleteV7RealTimeData(String sn) {
        radarDataService.deleteV7RealTimeData(sn);
    }


}
